<template>
	<!-- 左右纵向列表联动页面 -->
	<!-- 参考链接：https://blog.csdn.net/Chanyto/article/details/131994786 -->
    <view class="container">
        <!-- 顶部面板 -->
        <view class="top--panel">
            <!-- 顶部面板，可添加所需要放在页面顶部的内容代码。比如banner图 -->
            <view style="background-color: #ffaa00;text-align: center;font-size: 28rpx;padding: 10px 0;color: #fff;">
                <view>这里顶部内容占位区域，不需要则删除</view>
                <view>可添加需放在页面顶部的内容，比如banner、轮播图等</view>
            </view>
        </view>
        <!-- 滚动区域 -->
        <view class="scroll-panel" id="scroll-panel">
            <view class="list-box">
                <view class="left">
                    <scroll-view scroll-y="true" 
                        :style="{ 'height':scrollHeight + 'px' }" 
                        :scroll-with-animation="false"
                        >
                        <view class="item" 
                            v-for="(item,index) in cateData"
                            :key="index" 
                            :class="{ 'active':index===leftIndex }" 
                            :id="'left-'+index"
                            @tap="leftTap(index)"
                        >{{item.name}}</view>
                    </scroll-view>
                </view>
                <view class="main">
                    <scroll-view  scroll-y="true" :style="{ 'height':scrollHeight + 'px' }" @scroll="mainScroll" :scroll-into-view="scrollInto" :scroll-with-animation="false">
                        <view class="item main-item" v-for="(item,index) in cateName" :key="index" :id="'item-'+index" @tap="click">
                            <view class="title">
                                <view>cateName{{index}}</view>
                            </view>
                            <view class="goods" v-for="(item2,index2) in listData" :key="index2">
                                <image :src="item2.logo" mode=""></image>
                                <view>
                                    <view>item2.name {{index}}</view>
                                    <view class="describe">item2.subname {{index}}</view>
                                </view>
                            </view>
                        </view>
                        <view class="fill-last" :style="{ 'height':fillHeight + 'px' }"></view>
                    </scroll-view>
                </view>
            </view>
        </view>
        <!-- 底部面板 -->
        <view class="bottom-panel">
            <!-- 底部面板，可添加所需要放在页面底部的内容代码。比如购物车栏目 -->
            <view style="background-color: #ffaa00;text-align: center;font-size: 28rpx;padding: 10px 0;color: #fff;">
                <view>这里底部内容占位区域，不需要则删除</view>
                <view>可添加需放在页面底部的内容，比如购物车栏目</view>
            </view>
        </view>
    </view>
    
</template>
​
<script>
    export default {
        data() {
            return {
                scrollHeight:400, // 默认高度
                scrollTopSize:0, // 默认顶部高度
                fillHeight:0,   // 填充高度，用于最后一项低于滚动区域时使用
                topArr:[], // 左侧列表元素
                leftIndex:0, // 点击切换存储的下标
                scrollInto:'', // 左侧定位
                cateData: [{"name": "category1"}, {"name": "category2"}, {"name": "category3"}],
                cateName: [1, 2, 3],
                listData: [1, 2, 3, 4, 5, 6, 7]
                
            }
        },
        created() {
            // this.onRightListFetch()
            // this.onLeftListFetch()
            // 这里如果上面请求超过500ms同样获取不到元素
            // setTimeout(() => {
            //  console.log('this.cateData',this.cateData);
            //  this.getElementTop()
            //  this.initScrollView()
            // }, 500)
			// this.initScrollView()
        },
		onReady() {
			this.initScrollView()
			this.getElementTop()
		},
        methods: {
            /* 初始化滚动区域 */
            initScrollView(){
                return new Promise((resolve, reject)=>{
                    let view = uni.createSelectorQuery().select('#scroll-panel');
                    view.boundingClientRect(res => {
                        this.scrollTopSize = res.top;
                        this.scrollHeight = res.height;
                        setTimeout(()=>{
                            resolve();
                        },100);
                    }).exec();
                });
            },
            // 获取右边数据
            async onRightListFetch() {
                const res = await this.$store.dispatch("tool/getToolList", {
                    
                });
                if ([100].includes(res.code)) {
                    this.listTotal = res.result.tltal
                    this.listData = res.result.data || []
                    let map = new Map();
                    for (let item of this.listData) {
                        map.set(item.cateId, item);
                    }
                    this.cateName = [...map.values()].sort((a,b) => {return a.cateId - b.cateId});
                    this.$nextTick(()=> {
                        this.getElementTop()
                        this.initScrollView()
                    })
                } else {
                    this.$toast(res.msg);
                }
            },
            // 获取左边数据
            async onLeftListFetch() {
                const res = await this.$store.dispatch('tool/getCateList')
                if ([100].includes(res.code)) {
                    this.cateTotal = res.result.total
                    this.cateData = res.result.data.sort((a,b) => {return a.id - b.id}) || []
                    this.loading = false
                } else {
                    this.$toast(res.msg)
                }
            },
            /* 获取元素顶部信息 */
            getElementTop(){
                new Promise((resolve,reject)=>{
                    let view = uni.createSelectorQuery().selectAll('.main-item');
                    view.boundingClientRect(data => {
                        resolve(data);
                    }).exec();
                }).then((res)=>{
                    console.log('res',res);
                    let topArr = res.map((item)=>{
                        return item.top - this.scrollTopSize;   /* 减去滚动容器距离顶部的距离 */
                    });
                    this.topArr = topArr;
                    /* 获取最后一项的高度，设置填充高度。判断和填充时做了 +-20 的操作，是为了滚动时更好的定位 */
                    let last = res[res.length-1].height;            
                    if(last - 20 < this.scrollHeight){
                        this.fillHeight = this.scrollHeight - last + 20;
                    }
                });
            },
            /* 主区域滚动监听 */
            mainScroll(e){
				// console.log("mainscroll:", JSON.stringify(e))
                // 节流方法
                clearTimeout(this.mainThrottle);
                this.mainThrottle = setTimeout(this.scrollFn(e),10);
     //            let scrollFn = ()=>{
     //                /* 查找当前滚动距离 */
					// for (var i = this.topArr.length - 1; i >= 0; --i) {
					// 	if((e.detail.scrollTop+2)>=this.topArr[i]){
					// 		if(this.leftIndex === i) {
					// 			break
					// 		} else {
					// 			this.leftIndex= i
					// 		}
					// 	    // index = i;
					// 	    //(index < 0 ? 0: index);
					// 		break;
					// 	}
					// }
     //            }
            },
			
			scrollFn(e) {
				/* 查找当前滚动距离 */
				for (var i = this.topArr.length - 1; i >= 0; --i) {
					if((e.detail.scrollTop+2)>=this.topArr[i]){
						if(this.leftIndex === i) {
							break
						} else {
							this.leftIndex= i
						}
					    // index = i;
					    //(index < 0 ? 0: index);
						break;
					}
				}
			},
			
            /* 左侧导航点击 */
            leftTap(e){
                this.leftIndex = e
                this.scrollInto="item-" + e;
            }
        }
    }
</script>
​
<style lang="scss">
page{
    height: 100vh;
}
.container{
    height: 100%;
}
/* 容器 */
.container{
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: flex-start;
    align-content: flex-start;
    
    &>view{
        width: 100%;
    }
    
    .scroll-panel{
        flex-grow: 1;
        height: 0;
        overflow: hidden;
    }
    
    .bottom-panel{
        padding-bottom: 0;
        padding-bottom: constant(safe-area-inset-bottom);  
        padding-bottom: env(safe-area-inset-bottom);        
    }
}
    
    
.list-box{
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: flex-start;
    align-content: flex-start;
    font-size: 28rpx;
    
    .left{
        width: 200rpx;
        background-color: #f6f6f6;
        line-height: normal;
        box-sizing: border-box;
        font-size: 32rpx;
        
        .item{
            padding: 30rpx;
            position: relative;
            
            
            & + .item{
                margin-top: 1px;
                            
                &::after {
                    content: '';
                    display: block;
                    height: 0;
                    border-top: #d6d6d6 solid 1px;
                    width: 620upx;
                    position: absolute;
                    top: -1px;
                    right: 0;
                    transform:scaleY(0.5);  /* 1px像素 */
                }
            }
            
            &.active{
                color: #42b983;
                background-color: #fff;
                position: relative;
                
                &::before{
                    content: '';
                    display: block;
                    position: absolute;
                    top: 0;
                    left: 0;
                    border-left: #42b983 solid 4px;
                    height: 100%;
                    width: 0;
                }
            }
        }
        
        .fill-last{
            height: 0;
            width: 100%;
            background: none;
        }
    }
    .main{
        background-color: #fff;
        padding-left: 20rpx;
        width: 0;
        flex-grow: 1;
        box-sizing: border-box;
        
        
        
        .title{
            line-height: normal;
            padding: 30rpx 0;
            font-size: 24rpx;
            font-weight: bold;
            color: #666;
            background-color: #fff;
            position: sticky;
            top: 0;
            z-index: 19;
        }
        
        .item{
            padding-bottom: 16rpx;
            border-bottom: #eee solid 1px;
        }
        
        .goods{
            display: flex;
            flex-direction: row;
            flex-wrap: nowrap;
            justify-content: flex-start;
            align-items: center;
            align-content: center;
            
            & + .goods{
                margin-top: 16rpx;
            }
            
            & > image{
                width: 120rpx;
                height: 120rpx;
                margin-right: 16rpx;
                margin-left: 2px;
            }
            
            .describe{
                font-size: 24rpx;
                color: #999;
            }
            
            .money{
                font-size: 24rpx;
                color: #efba21;
            }
        }
    }
}
</style>